/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package za.co.pas.business.data;

import java.io.Serializable;
import java.util.Calendar;
import java.util.LinkedList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Transient;
import za.co.pas.business.constant.Constant;
import za.co.pas.business.data.audit.Address_AUDIT;

/**
 *
 * @author alabuschagne
 */
@Entity
public class Address implements Serializable
{

    private static final long serialVersionUID = 1L;
    private Long id;
    private String line1 = "";
    private String line2 = "";
    private String suburb = "";
    private String city = "";
    private String code = "";
    private Province province;
    private Country country;
    private boolean processed = false;
    private List<Address_AUDIT> addressAuditList = new LinkedList<Address_AUDIT>();

    public Address()
    {
        province = new Province();
        country = new Country();
    }

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    public Long getId()
    {
        return id;
    }

    public void setId(Long id)
    {
        this.id = id;
    }

    @Override
    public int hashCode()
    {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object)
    {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Address))
        {
            return false;
        }
        Address other = (Address) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id)))
        {
            return false;
        }
        return true;
    }

    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        if ((line1 != null) && (line1.length() > 0))
        {
            sb.append(line1);
        }
        if ((line2 != null) && (line1.length() > 0))
        {
            sb.append("|");
            sb.append(line2);
        }
        if ((suburb != null) && (line1.length() > 0))
        {
            sb.append("|");
            sb.append(suburb);
        }
        if ((city != null) && (line1.length() > 0))
        {
            sb.append("|");
            sb.append(city);
        }
        if (province != null)
        {

            sb.append("|");
            sb.append(province.toString());
        }
        if (country != null)
        {
            sb.append("|");
            sb.append(country.toString());
        }
        if ((code != null) && (line1.length() > 0))
        {
            sb.append("|");
            sb.append(code);
        }
        return sb.toString();
    }

    /**
     * @return the line1
     */
    public String getLine1()
    {
        return line1;
    }

    /**
     * @param line1 the line1 to set
     */
    public void setLine1(String line1)
    {
        this.line1 = line1;
    }

    /**
     * @return the line2
     */
    public String getLine2()
    {
        return line2;
    }

    /**
     * @param line2 the line2 to set
     */
    public void setLine2(String line2)
    {
        this.line2 = line2;
    }

    /**
     * @return the suburb
     */
    public String getSuburb()
    {
        return suburb;
    }

    /**
     * @param suburb the suburb to set
     */
    public void setSuburb(String suburb)
    {
        this.suburb = suburb;
    }

    /**
     * @return the city
     */
    public String getCity()
    {
        return city;
    }

    /**
     * @param city the city to set
     */
    public void setCity(String city)
    {
        this.city = city;
    }

    /**
     * @return the code
     */
    public String getCode()
    {
        return code;
    }

    /**
     * @param code the code to set
     */
    public void setCode(String code)
    {
        this.code = code;
    }

    /**
     * @return the province
     */
    @ManyToOne(cascade = CascadeType.ALL)
    public Province getProvince()
    {
        return province;
    }

    /**
     * @param province the province to set
     */
    public void setProvince(Province province)
    {
        this.province = province;
    }

    /**
     * @return the country
     */
    @ManyToOne(cascade = CascadeType.ALL)
    public Country getCountry()
    {
        return country;
    }

    /**
     * @param country the country to set
     */
    public void setCountry(Country country)
    {
        this.country = country;
    }

    public boolean check(Address otherAddress)
    {
        if (otherAddress == null)
        {
            return false;
        }
        if (id == null)
        {
            return false;
        }
        else if ((line1 == null) && (otherAddress.getLine1() != null))
        {
            return false;
        }
        else if ((line1 != null) && (line1.compareTo(otherAddress.getLine1()) != 0))
        {
            return false;
        }
        else if ((line2 == null) && (otherAddress.getLine2() != null))
        {
            return false;
        }
        else if ((line2 != null) && (line2.compareTo(otherAddress.getLine2()) != 0))
        {
            return false;
        }
        else if ((suburb == null) && (otherAddress.getSuburb() != null))
        {
            return false;
        }
        else if ((suburb != null) && (suburb.compareTo(otherAddress.getSuburb()) != 0))
        {
            return false;
        }
        else if ((city == null) && (otherAddress.getCity() != null))
        {
            return false;
        }
        else if ((city != null) && (city.compareTo(otherAddress.getCity()) != 0))
        {
            return false;
        }
        else if ((code == null) && (otherAddress.getCode() != null))
        {
            return false;
        }
        else if ((code != null) && (code.compareTo(otherAddress.getCode()) != 0))
        {
            return false;
        }
        else if ((province == null) && (otherAddress.getProvince() != null))
        {
            return false;
        }
        else if ((province != null) && (!province.check(otherAddress.getProvince())))
        {
            return false;
        }
        else if ((country == null) && (otherAddress.getCountry() != null))
        {
            return false;
        }
        else if ((country != null) && (!country.check(otherAddress.getCountry())))
        {
            return false;
        }
        return true;
    }

    @Override
    public Address clone()
    {
        Address newAddress = new Address();
        newAddress.setCity(city);
        newAddress.setCode(code);
        newAddress.setCountry(country.clone());
        newAddress.setId(id);
        newAddress.setLine1(line1);
        newAddress.setLine2(line2);
        Province p = province.clone();
        p.setCountry(newAddress.getCountry());
        newAddress.setProvince(p);
        newAddress.setSuburb(suburb);
        return newAddress;
    }

    /**
     * @return the processed
     */
    @Transient
    public boolean isProcessed()
    {
        return processed;
    }

    /**
     * @param processed the processed to set
     */
    public void setProcessed(boolean processed)
    {
        this.processed = processed;
    }

    private void makeAudit(Company company, String colName, UserLoginDetails uld, Object oldValue, Object newValue)
    {
        Address_AUDIT ca = new Address_AUDIT();
        ca.setColName(colName);
        ca.setChangedAt(Calendar.getInstance());
        ca.setChangedBy(uld);
        if (getId() != null)
        {
            ca.setCompany(company);
        }
        else
        {
            ca.setCompany(null);//new
        }
        ca.setLongId(getId());
        if (newValue != null)
        {
            ca.setNewValue(newValue.toString());
        }
        else
        {
            ca.setNewValue(null);
        }

        if (oldValue != null)
        {
            ca.setOldValue(oldValue.toString());
        }
        else
        {
            ca.setOldValue(null);
        }
        add(ca);
    }

    public boolean set(Company company, UserLoginDetails uld, Address address)
    {
        boolean updated = false;
        if (address == null)
        {
            return updated;
        }
        if (!Constant.stringCompare(getCity(), address.getCity()))
        {
            makeAudit(company, "CITY", uld, getCity(), address.getCity());
            setCity(address.getCity());
            updated = true;
        }
        if (!Constant.stringCompare(getCode(), address.getCode()))
        {
            makeAudit(company, "CODE", uld, getCode(), address.getCode());
            setCode(address.getCode());
            updated = true;
        }
        if (!Constant.stringCompare(getLine1(), address.getLine1()))
        {
            makeAudit(company, "LINE1", uld, getLine1(), address.getLine1());
            setLine1(address.getLine1());
            updated = true;
        }
        if (!Constant.stringCompare(getLine2(), address.getLine2()))
        {
            makeAudit(company, "LINE2", uld, getLine2(), address.getLine2());
            setLine2(address.getLine2());
            updated = true;
        }
        if (!Constant.stringCompare(getSuburb(), address.getSuburb()))
        {
            makeAudit(company, "SUBURB", uld, getSuburb(), address.getSuburb());
            setSuburb(address.getSuburb());
            updated = true;
        }
        boolean update = false;
        if ((getCountry() != null) && (address.getCountry() != null))
        {
            update = getCountry().check(address.getCountry());
        }
        else if ((getCountry() == null) && (address.getCountry() != null))
        {
            update = true;
        }
        else if ((getCountry() != null) && (address.getCountry() == null))
        {
            update = true;
        }
        if (update)
        {
            makeAudit(company, "COUNTRY", uld, getCountry(), address.getCountry());
            setCountry(address.getCountry());
            updated = true;
        }
        update = false;
        if ((getProvince() != null) && (address.getProvince() != null))
        {
            update = getProvince().check(address.getProvince());
        }
        else if ((getProvince() == null) && (address.getProvince() != null))
        {
            update = true;
        }
        else if ((getProvince() != null) && (address.getProvince() == null))
        {
            update = true;
        }
        if (update)
        {
            makeAudit(company, "PROVINCE", uld, getProvince(), address.getProvince());
            setProvince(address.getProvince());
            updated = true;
        }
        return updated;
    }

    private void add(Address_AUDIT ca)
    {
        if (addressAuditList == null)
        {
            addressAuditList = new LinkedList<Address_AUDIT>();
        }
        addressAuditList.add(ca);
    }

    /**
     * @return the addressAuditList
     */
    @Transient
    public List<Address_AUDIT> getAddressAuditList()
    {
        return addressAuditList;
    }

    /**
     * @param addressAuditList the addressAuditList to set
     */
    public void setAddressAuditList(List<Address_AUDIT> addressAuditList)
    {
        this.addressAuditList = addressAuditList;
    }

    public String logPrint(int level)
    {
        StringBuilder tab = new StringBuilder();
        for(int i = 0; i < level; i++)
        {
            tab.append("\t");
        }
        StringBuilder sb = new StringBuilder(tab.toString());
        sb.append("ADDRESS\n");
        sb.append(tab.toString());
        sb.append("ID: \t");
        sb.append(id);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Line 1: \t");
        sb.append(line1);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Line 2: \t");
        sb.append(line2);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Suburb: \t");
        sb.append(suburb);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("City: \t");
        sb.append(city);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Code: \t");
        sb.append(code);
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Province: \t");
        int l2 = level + 1;
        sb.append(province.logPrint(l2));
        sb.append("\n");
        sb.append(tab.toString());
        sb.append("Country: \t");
        sb.append(country.logPrint(l2));
        return sb.toString();
    }
}
